Ansibleのテストで使いたい8つのServerspec
渡辺です。
Ansibleを使っている皆様、テスト書いてますか?
え、書いてない?
弊社では、社内共有しているAnsibleのRoleの検証にServerspecを利用しています。 今日はよく使うリソースタイプを紹介します。
テストの流れ
テストのフレームワークとしてはTest Kitchenを利用しています(kitchen-ansiblepushを利用したAnsible roleのテスト環境構築)。 はじめに、Test KitchenのEC2 Driverを利用し、AWS環境にEC2インスタンスを作成します。 次に、ひとつのRoleを実行するAnsibleのPlaybookを流します。 続けて、サーバの状態が期待された状態になっているかをServerspecで検証します。 最後に、AWS環境にEC2インスタンスが破棄されます(検証失敗時は破棄されない)。
Ansibleでもテストの仕組みが提供されています。 しかし、ユニットテストに近い仕組みであり、実際に起動したEC2インスタンスに適用できるかは保障されません。 このため、インテグレーションテストに近いテストの仕組みを採用しています(Ansibleのテスト事情)。
specファイルでの検証
テストの検証にはServerspecを利用します。 Serverspecでは、サーバの状態を「こうあるべきだ」というDSL風に記述します。 ほとんどのケースで同じように書けばいいので、基本的にコピペで大丈夫です。 「こういう時はどうするんだろう?」という時にドキュメントを参照しましょう。
サービスの状態を検証する
httpdやその他サービスがインストールされていることを検証するには、serviceを利用します。
describe service('httpd') do it { should be_running } it { should be_enabled } end
service
の引数を変更すれば、他のサービスでも同様に検証できるでしょう。
be_enabled
で、サービスの自動起動が有効化されていること検証します。
なお、インストールされていないことを確認するには、以下のようにshould_not
を使います。
# iptables should be disabled describe service('iptables') do it { should_not be_running } it { should_not be_enabled } end
プロセスが起動していることを検証する
httpdのようにサービスとして設定されていない場合、processを利用することで、プロセスとして起動しているかを検証出来ます。
describe process("amazon-ssm-agent") do it { should be_running } end
パッケージの存在を検証する
パッケージがインストールされていることを検証するにはpackageを利用します。
describe package('awscli') do it { should be_installed.by('pip') } end
この例では、be_installed
だけではなく、さらにそのパッケージがpipでインストールされていることまでを検証しています。
.by('pip')
は省略できます。
変更したファイルの内容を検証する
テキストファイルの内容を検証するには、fileを利用します。
さらに、以下のような書式でcontent
(本文)を正規表現などで検証してください。
describe file('/etc/sysconfig/i18n') do its(:content) { should match /LANG=ja_JP\.UTF-8/ } end
この書き方を知っていれば概ね問題無いと思います。
ディレクトリの存在を検証する
作成したディレクトリの存在を検証するには、fileを利用します。
describe file('/opt/classmethod/monitoring') do it { should be_directory } it { should be_owned_by 'cm-mon' } it { should be_grouped_into 'cm-mon' } end
属性は、be_directory
やbe_owned_by
などで検証しましょう。
ユーザとグループの存在を検証する
作成したユーザやグループの存在を確認するには、groupやuserを利用します。
describe group('cm-mon') do it { should exist } end describe user('cm-mon') do it { should exist } end
cronの設定を検証する
cronの設定はcronで検証します。
describe cron do it { should have_entry('*/5 * * * * /opt/classmethod/monitoring/diskUsage.sh').with_user('cm-mon') } it { should have_entry('*/5 * * * * /opt/classmethod/monitoring/memoryUsage.sh').with_user('cm-mon') } end
コマンドの実行結果を検証する
Roleで色々設定した結果、あるコマンドを実行して確認したいというケースは多いです。 そんな時は、commandを利用します。
describe command('date') do its(:stdout) { should match /JST/ } end
システムのタイムゾーンを変更した後、date
コマンドを実行して、結果にJSTが含まれることを検証しています。
この辺りがインテグレーションテスト的な検証ですね。
まとめ
今回紹介したリソースを利用すれば、9割以上のスペック(テスト)は書けると思います。 スペックの書き方はほとんど変わらないので、Roleを作ったら息を吸うようにスペックを書きましょう。
さばんなちほーでも「Ansible Roleのテスト書いてるぜ」と言えるようにしてください。